package com.hoshiicloud.purchase.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hoshiicloud.common.api.dto.EncryptedResponseDTO;
import com.hoshiicloud.common.constant.QueueConsts;
import com.hoshiicloud.common.exception.CommonError;
import com.hoshiicloud.common.exception.ServiceException;
import com.hoshiicloud.common.rpc.Response;
import com.hoshiicloud.common.utils.EncryptionUtil;
import com.hoshiicloud.common.utils.UidGenerate4C;
import com.hoshiicloud.goods.dto.sku.SkuDTO;
import com.hoshiicloud.purchase.Po;
import com.hoshiicloud.purchase.Podetail;
import com.hoshiicloud.purchase.Worksheet;
import com.hoshiicloud.purchase.config.RsaConfig;
import com.hoshiicloud.purchase.feign.GoodsService;
import com.hoshiicloud.purchase.feign.OrderService;
import com.hoshiicloud.purchase.feign.StockService;
import com.hoshiicloud.purchase.service.PoService;
import com.hoshiicloud.purchase.service.PodetailService;
import com.hoshiicloud.purchase.service.PurchaseService;
import com.hoshiicloud.purchase.service.WorksheetService;
import com.hoshiicloud.saleorder.entity.OrderInfo;
import com.hoshiicloud.saleorder.entity.OrderMain;
import com.hoshiicloud.saleorder.param.OrderInfoQueryParam;
import com.hoshiicloud.saleorder.param.OrderMainUpdateParam;
import com.hoshiicloud.stock.entity.WarehouseList;
import com.hoshiicloud.stock.param.WarehouseListPageParam;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author:campchen
 * @Date:Created in 上午 11:51 2019/5/31
 * @PACKAGENAME com.hoshiicloud.purchase.service.impl
 * @Description
 */
@Slf4j
@Service
public class PurchaseServiceImpl implements PurchaseService {

    @Autowired
    private PoService poService;
    @Autowired
    private PodetailService podetailService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private StockService stockService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private WorksheetService worksheetService;

    //采购单--销售订单自动生成--9  备货单--采购人员采购--2
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "Po", allEntries = true)
    @Override
    public boolean saveActualPurchase(Po poParam, List<Podetail> list) {
        int num = 1;
        boolean flag = true;
        String code = null;
        UidGenerate4C idWorker = new UidGenerate4C(num);
        while (flag) {
            code = String.valueOf(idWorker.getNextId()).substring(7, 17);
            num++;
            Po po = poService.getByCode(code);
            if (po == null || "".equals(po)) {
                flag = false;
            }
            if (num > 1000) {
                throw new ServiceException(
                        CommonError.error("com.hoshiicloud.purchase.service.impl编码生成重复1000次，请联系管理员！"));
            }
        }
        poParam.setPoNo(code);
        flag = poService.save(poParam);
        if (!flag) {
            throw new ServiceException(CommonError.error("新采购单异常"));
        }
        for (Podetail p : list) {
            p.setPoId(poParam.getId());
        }
        try {
            podetailService.saveBatch(list);
        } catch (Exception e) {
            throw new ServiceException(CommonError.error("新增采购详情异常"));
        }
        return true;
    }


    /**
     * 采购订单回调消息处理 TODO 添加分布式事务
     *
     * @param message
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @RabbitListener(queues = QueueConsts.PUSH_PO_QUEUE)
    @RabbitHandler
    public void poCallBackprocess(Message message) {
        try {
            log.info("采购策略处理开始:");
            //收到加密后数据进行解密
            log.info("接受回调消息" + message.toString());
            //获取请求体转换
            String body = new String(message.getBody());
            log.info("body:" + body);
            System.out.println(body);
            String json = new String(Base64.getMimeDecoder().decode(body.replace("\r\n", "")));
            Set<Long> mainOrderIdSet = EncryptionUtil
                    .decryptData(json, RsaConfig.getClientPublicKey(), RsaConfig.getServerPrivateKey(), Set.class);
            if (mainOrderIdSet == null) {
                //验签失败
                throw new ServiceException("解析消息失败，验签失败");
            }
            log.info("data:" + mainOrderIdSet.toString());
            /**
             * 根据主订单id列表查找相关的主订单信息
             * 根据主订单信息查找相应的子订单信息
             * 根据子订单对应的商品的采购策略查找相应的供应商
             * 根据供应商分组生成采购单和相应的采购单明细
             * 如果主订单中的采购出现异常，则生成处理工单
             */
            List<Long> mainOrderIdList = new ArrayList<>(mainOrderIdSet);
            //查询主订单信息
            Response tempMainResult = orderService.getOrderMainByIds(mainOrderIdList);
            List<OrderMain> orderMainList = (List<OrderMain>) tempMainResult.getData();
            Map<Long, OrderMain> orderMainMap = new HashMap<>();
            for (OrderMain orderMain : orderMainList) {
                Integer equalsTwo = 2;
                if (!equalsTwo.equals(orderMain.getOrderStatus())) {
                    //已支付状态才执行采购策略
                    mainOrderIdList.remove(orderMain.getId());
                } else {
                    orderMainMap.put(orderMain.getId(), orderMain);
                }
            }
            if (mainOrderIdList.size() == 0) {
                log.error("没有符合条件的订单,不执行采购策略");
                return;
            }

            Map<Long, List<OrderInfo>> orderMap = new HashMap<>(16);
            Map<Long, List<Long>> baseSkuIdMap = new HashMap<>(16);
            Map<Long, List<Long>> extSkuIdMap = new HashMap<>(16);
            OrderInfoQueryParam orderInfoQueryParam = new OrderInfoQueryParam();
            orderInfoQueryParam.setMainId(mainOrderIdList);
            orderInfoQueryParam.setPageSize("1000");
            //查询主订单相关的子订单信息
            Response result = orderService.getOrderInfoPage(orderInfoQueryParam);
            IPage<OrderInfo> t = (IPage<OrderInfo>) result.getData();
            List<OrderInfo> tlist = t.getRecords();
            List<Long> baseSkuIdList = new ArrayList<>();
            List<Long> extSkuIdList = new ArrayList<>();
            for (OrderInfo order : tlist) {
                //根据主单分组
                List<OrderInfo> orderInfoList = orderMap.get(order.getMainId());
                if (orderInfoList == null) {
                    orderInfoList = new ArrayList<OrderInfo>();
                    orderInfoList.add(order);
                    orderMap.put(order.getMainId(), orderInfoList);
                }
                //保存所有扩展sku的id用于查询
                extSkuIdList.add(order.getSkuId());
            }

            // Response<Map<Long, SkuDTO>> skuDtoResult = goodsService.getSkuStockByIds(extSkuIdList);
            //TODO 获取dto方法待添加缓存
            Response<Map<Long, SkuDTO>> skuDtoResult = goodsService.queryHeadOfficeSkuStockByIds(extSkuIdList);
            Map<Long, SkuDTO> skuDTOMap = skuDtoResult.getData();
            Map<Long, Po> poMap = new HashMap<>();
            Map<Long, List<Podetail>> poDetailListMap = new HashMap<>();
            Map<Long, String> exceptionalMsgMap = new HashMap<>();
            boolean purchaseSuccess = true;
            Long vendorId = null;
            WarehouseListPageParam warehouseListPageParam = new WarehouseListPageParam();
            warehouseListPageParam.setPageSize(1000L);
            warehouseListPageParam.setDeleted(0);
            for (Map.Entry<Long, List<OrderInfo>> entry : orderMap.entrySet()) {
                List<OrderInfo> temp = entry.getValue();
                WarehouseList warehouseList = null;
                purchaseSuccess = true;
                mainOrder:
                for (OrderInfo order : temp) {
                    SkuDTO skuDetail = skuDTOMap.get(order.getSkuId());
                    String exceptionalMsg = exceptionalMsgMap.putIfAbsent(order.getMainId(), "");

                    if (skuDetail.getVendorSelf().equals(1)) {
                        //自供商品不生成采购单
                        continue;
                    }
                    //根据采购策略判断是否生成采购单
                    if (skuDetail.getStrategy().equals(1)) {
                        //指定的供应商为空且非自供商品,产生采购异常工单
                        if (skuDetail.getVendorId() == null) {
                            exceptionalMsg +=
                                    "编号为" + order.getId() + "的订单中的编号为" + skuDetail.getSkuId() + "的商品没有指定供应商，请及时处理;";
                            purchaseSuccess = false;
                            continue;
                        } else {
                            //指定供应商
                            //找到指定供应商的仓库，判断库存数量是否足够
                            warehouseListPageParam.setVendor(skuDetail.getVendorId());
                        }
                    } else if (skuDetail.getStrategy().equals(2)) {
                        //系统派单
                        //如果找不到合适的供应商采购,产生采购异常工单
                        //对应商品供应商
                        //找到供应商的仓库，判断库存数量是否足够
                        //TODO 选择成本最低的供应商
                        warehouseListPageParam.setVendor(null);
                    }
                    //系统派单和指定供应商的区别是查询条件是否设置

                    warehouseListPageParam.setBalance(new BigDecimal(order.getQuantity()));
                    //根据基础skuid查找
                    warehouseListPageParam.setSkuId(skuDetail.getSkuId());
                    Response<IPage<WarehouseList>> tStockResult = stockService
                            .getWarehouseListPage(warehouseListPageParam);
                    if (tStockResult == null) {
                        //TODO 查询库存业务失败,异常处理
                        //系统异常跳过后续订单处理
                        exceptionalMsg += "编号为" + order.getId() + "的订单采购策略查询库存发生异常,请联系技术部及时处理";
                        purchaseSuccess = false;
                        continue;
                    }

                    IPage<WarehouseList> warehouseListIPage = tStockResult.getData();
                    List<WarehouseList> warehouseLists = warehouseListIPage.getRecords();
                    if (warehouseLists.size() == 0) {
                        exceptionalMsg +=
                                "编号为" + order.getId() + "的订单中的编号为" + skuDetail.getSkuId() + "的商品无法找到符合条件的供应商，请及时处理;";
                        purchaseSuccess = false;
                        continue;
                    }
                    if (!purchaseSuccess) {
                        continue;
                    } else {
                        //生成采购单明细
                        warehouseList = warehouseLists.get(0);
                        vendorId = warehouseList.getVendor();
                        //生成采购单与采购单明细
                        List<Podetail> podetailList = poDetailListMap.putIfAbsent(vendorId, new ArrayList<>());
                        Podetail podetail = new Podetail();
                        podetail.setSpuName(skuDetail.getSpuTitle());
                        podetail.setSkuName(skuDetail.getSkuTitle());
                        podetail.setSpuNo(skuDetail.getSpuNo());
                        podetail.setSpuId(skuDetail.getSpuId());
                        podetail.setSkuNo(warehouseList.getSkuno());
                        podetail.setSkuId(skuDetail.getSkuId());
                        podetail.setUnit(warehouseList.getUnit());
                        //规格
                        podetail.setSku(warehouseList.getSpec());
                        podetail.setUnitPrice(skuDetail.getGoodsPrice());
                        podetail.setQuantity(order.getQuantity());

                        podetail.setStatus(1);

                        //税率暂时默认为0
                        podetail.setRate(BigDecimal.ZERO);
                        podetail.setAmount(
                                podetail.getUnitPrice().multiply(new BigDecimal(podetail.getQuantity()).setScale(2)));
                        podetail.setRatefee(podetail.getAmount().multiply(podetail.getRate()));
                        //合计金额 = 金额+ 税额
                        podetail.setTotalAmount(podetail.getAmount().add(podetail.getRatefee()));
                        podetailList.add(podetail);
                        Po po = poMap.get(vendorId);
                        if (po == null) {
                            OrderMain orderMain = orderMainMap.get(order.getMainId());
                            po = new Po();
                            po.setCompanyId(warehouseList.getCompanyid());
                            po.setPlatformId(warehouseList.getPlatformid());
                            po.setStoreId(warehouseList.getStoreid());
                            po.setVendorId(vendorId);
                            po.setMemberId(order.getMemberId());
                            po.setAddress(orderMain.getAddress());

                            //订单状态  0-初始下单 2-已确认 3-执行中 4-已完成 5-已作废
                            po.setStatus(0);
                            //结算状态  1-已结算  0-未结算
                            po.setSettleStatus(0);
                            //结算金额
                            po.setSettleAmount(podetail.getTotalAmount());
                            po.setOrderAmount(podetail.getTotalAmount());
                            po.setOrderCount(podetail.getQuantity());
                            po.setSalesOrderId(orderMain.getId());
                            po.setCreatedBy("系统生成");
                            po.setCreatedTime(LocalDateTime.now());
                            poMap.put(vendorId, po);
                        } else {
                            po.setSettleAmount(po.getSettleAmount().add(podetail.getTotalAmount()));
                            po.setOrderAmount(po.getOrderAmount().add(podetail.getTotalAmount()));
                            po.setOrderCount(po.getOrderCount() + podetail.getQuantity());
                        }
                    }
                }
            }
            Set<Long> successOrderMainIdList = new HashSet<>();
            List<Worksheet> worksheetList = new ArrayList<>();
            for (Map.Entry<Long, OrderMain> entry : orderMainMap.entrySet()) {
                if (StringUtils.isNotBlank(exceptionalMsgMap.get(entry.getKey()))) {
                    //TODO 如果异常信息不为空,生成异常工单
                    //TODO 根据工单配置设置相应属性

                    Worksheet worksheet = new Worksheet();
                    worksheet.setCompanyid(entry.getValue().getCompanyId());
                    worksheet.setPlatformid(entry.getValue().getPlatformId());
                    worksheet.setStoreid(entry.getValue().getStoreId());
                    worksheet.setName("采购策略异常");
                    //工单类型 1-采购 2-出库 3-入库 4-退款 5-换货 6-物流 7-退货8-商品
                    worksheet.setType(1);
                    //TODO 查找订单对应平台的处理人
                    worksheet.setUserId(null);
                    //TODO 查找处理部门
                    worksheet.setDepartmentId(null);
                    //不填为不限制截止时间
                    worksheet.setDeadlineTime(null);
                    worksheet.setDeadline(null);
                    worksheet.setPriority(1l);
                    worksheet.setDescription(exceptionalMsgMap.get(entry.getKey()));
                    worksheet.setCreatedby("系统生成");
                    worksheet.setCreatedtime(LocalDateTime.now());
                    //状态 1-待处理 2-已处理 3-已作废
                    worksheet.setStatus(1);
                    worksheetList.add(worksheet);
                } else {
                    //修改主订单状态
                    //TODO 改为批量更新
                    OrderMainUpdateParam orderMainUpdateParam = new OrderMainUpdateParam();
                    orderMainUpdateParam.setId(entry.getValue().getId());
                    //状态改为分配中
                    orderMainUpdateParam.setOrderStatus(3);
                    orderService.updateOrderMain(orderMainUpdateParam);
                    successOrderMainIdList.add(entry.getValue().getId());
                }
            }
            //保存采购单信息
            for (Map.Entry<Long, Po> entry : poMap.entrySet()) {
                List<Podetail> podetailList = poDetailListMap.get(entry.getKey());
                Po po = entry.getValue();
                saveActualPurchase(po, podetailList);
            }
            if (worksheetList.size() > 0) {
                //批量插入工单信息
                if (!worksheetService.saveBatch(worksheetList)) {
                    //抛出异常
                    throw new ServiceException("插入工单异常");
                }
            }
            //TODO 推送出库策略
            //出库策略推送主订单号列表
            pushToDo(successOrderMainIdList);
            log.info("采购流程结束");
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.toString());
            //throw e;
        }
    }

    /**
     * 推送销售主订单至仓库中心
     */
    private void pushToDo(Set<Long> orderMainIdSet) {
        //推送消息执行出库策略
        // todo 后续继续完善业务代码
        new Thread(() -> {
            try {
                EncryptedResponseDTO encryptData = EncryptionUtil
                        .encryptData(orderMainIdSet, RsaConfig.getClientPrivateKey(),
                                RsaConfig.getServerPublicKey());
                String data = JSON.toJSONString(encryptData);
                String base64Info = Base64.getEncoder().encodeToString(data.getBytes());
                rabbitTemplate.convertAndSend(QueueConsts.PUSH_DO_QUEUE, base64Info);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

}
